﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ngram
{
    class Model3
    {
        public string process(string input)
        {
            string[] wordUsArr = input.Split(' ');
            Dictionary<string, double> rs = null;
            Dictionary<string,double> tempRS=null;
            Dictionary<string, double> listWords;
            string[] wordArr;
            string lastWord;
            if (wordUsArr.Length >= 1)
            {
                if (Data.P_One.ContainsKey(wordUsArr[0]))
                {
                    rs = Data.P_One[wordUsArr[0]];
                }
                else
                {
                    rs = new Dictionary<string, double>();
                    rs.Add(wordUsArr[0], Data.ThresholdNotFound);
                }
                if (wordUsArr.Length >= 2)
                {
                    tempRS = new Dictionary<string, double>();
                    if(Data.P_One.ContainsKey(wordUsArr[1]))
                    {
                        listWords = Data.P_One[wordUsArr[1]];
                    }else
                    {
                        listWords = new Dictionary<string, double>();
                        listWords.Add(wordUsArr[1], Data.ThresholdNotFound);
                    }
                    foreach (KeyValuePair<string, double> r in rs)
                    {
                        foreach (KeyValuePair<string, double> lw in listWords)
                        {
                            wordArr = r.Key.Split(' ');
                            lastWord = wordArr[wordArr.Length - 1];
                            //Console.WriteLine(lastWord + " " + lw.Key + " = " + r.Value * S(lastWord + " " + lw.Key,lw.Key));
                            tempRS.Add(r.Key + " " + lw.Key,r.Value * S(lastWord+" "+lw.Key,lw.Key)*1.0);
                        }
                    }
                    if (Data.AllowFilter)
                    {
                        rs = getRSForCount(tempRS, Data.ThresholdFilter);
                    }
                    else
                    {
                        rs = tempRS;
                    }
                    if (wordUsArr.Length >= 3)
                    {
                        for (int i = 1; i < wordUsArr.Length - 1; i++)
                        {
                            tempRS = new Dictionary<string, double>();
                            if (Data.P_One.ContainsKey(wordUsArr[i+1]))
                            {
                                listWords = Data.P_One[wordUsArr[i+1]];
                            }
                            else
                            {
                                listWords = new Dictionary<string, double>();
                                listWords.Add(wordUsArr[i+1], Data.ThresholdNotFound);
                            }
                            foreach (KeyValuePair<string, double> r in rs)
                            {
                                foreach (KeyValuePair<string, double> lw in listWords)
                                {
                                    wordArr = r.Key.Split(' ');
                                    lastWord = wordArr[wordArr.Length - 1];
                                    //Console.WriteLine(lastWord + " " + lw.Key + " = " + r.Value * F(lastWord + " " + lw.Key));
                                    tempRS.Add(r.Key + " " + lw.Key, r.Value * S(lastWord + " " + lw.Key,lw.Key) * 1.0);
                                }
                            }
                            if (Data.AllowFilter)
                            {
                                rs = getRSForCount(tempRS,Data.ThresholdFilter);
                            }
                            else
                            {
                                rs = tempRS;
                            }
                        }
                    }
                }
            }
            if (rs != null)
                return getRS(rs);
            return "";
        }
        public double S(string w1w2,string w2)
        {
            string us = Utils.processUtils.ConvertToUnSign(w1w2);
            if (Data.F.ContainsKey(us))
            {
                if (Data.F[us].ContainsKey(w1w2))
                {
                    return Data.F[us][w1w2] * Data.P_One[Utils.processUtils.ConvertToUnSign(w2)][w2];
                }
                else
                {
                    return Data.ThresholdNotFound;
                }
            }
            return Data.ThresholdNotFound;
        }
        public string getRS(Dictionary<string, double> rs)
        {
            try
            {
                double max = rs.Max(kvp => kvp.Value);
                return rs.Where(kvp => kvp.Value == max).Select(kvp => kvp.Key).First();
            }
            catch (Exception)
            {
                return null;
            }
        }
        public Dictionary<string, double> getRSForCount(Dictionary<string, double> RS, int count)
        {
            var items = from pair in RS
                        orderby pair.Value descending
                        select pair;
            Dictionary<string, double> rs = new Dictionary<string, double>();
            foreach (KeyValuePair<string, double> pair in items)
            {
                if (count == 0)
                    return rs;
                count--;
                rs.Add(pair.Key, pair.Value);
            }
            return rs;
        }
    }
}
